#include "widget.h"
#include "ui_widget.h"
#include <QRadioButton>
#include <QPushButton>
#include <QDebug>
#include <QTextCodec>
#include <QTime>
#include <QCryptographicHash>
#include <QFileDialog>
#include <QDir>
#include <QFile>
#include <QtEndian>
#define STR_TOOL_VERSION "1.0.2"
#define RANDOM_SAMPLE "1234567890abcdefjhigklmnopqrstuvwxyzABCDEFJHIGKLMNOPQRSTUVWXYZ"
#define IS_IP_EXSTR "([1-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}"
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget),
    fun_type(IDLE),
    sample_str(RANDOM_SAMPLE)
{
    ui->setupUi(this);
    QString title = QString("%1-%2").arg("字符串小工具").arg(STR_TOOL_VERSION);
    this->setWindowTitle(title);
    ui->cover_button->setEnabled(false);
    setFixedSize(this->size());
    connect(ui->str2hex, &QRadioButton::clicked, this, &Widget::OnStr2Hex);
    connect(ui->hex2str, &QRadioButton::clicked, this, &Widget::OnHex2Str);
    connect(ui->cover_button, &QPushButton::clicked, this, &Widget::OnCoverBt);
    connect(ui->clear_button, &QPushButton::clicked, this, &Widget::OnClearBt);
    connect(ui->random256, &QRadioButton::clicked, this, &Widget::Onrandom256);
    connect(ui->MD5, &QRadioButton::clicked, this, &Widget::OnMd5);
    connect(ui->MD5file, &QRadioButton::clicked, this, &Widget::OnMd5File);
    connect(ui->str2utf8, &QRadioButton::clicked, this, &Widget::OnStr2Utf8);
    connect(ui->utf82str, &QRadioButton::clicked, this, &Widget::OnUtf82Str);
    connect(ui->str2unicode, &QRadioButton::clicked, this, &Widget::OnStr2Unicode);
    connect(ui->str2unicodeBig, &QRadioButton::clicked, this, &Widget::OnStr2UnicodeBig);
    connect(ui->unicode2str, &QRadioButton::clicked, this, &Widget::OnUnicode2Str);
    connect(ui->unicode2strBig, &QRadioButton::clicked, this, &Widget::OnUnicode2StrBig);
    connect(ui->int2ip, &QRadioButton::clicked, this, &Widget::Onint2ip);
    connect(ui->ip2int, &QRadioButton::clicked, this, &Widget::Onip2int);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::OnStr2Hex()
{
    fun_type = STR2HEX;
    do_fun_init();
    qDebug()<<"enter OnStr2Hex "<<fun_type<<endl;
}

void Widget::OnHex2Str()
{
    fun_type = HEX2STR;
    do_fun_init();
    qDebug()<<"enter OnHex2Str "<<fun_type<<endl;
}
void Widget::OnStr2Utf8()
{
    fun_type = STR2UTF8;
    do_fun_init();
    qDebug()<<"enter OnStr2Utf8 "<<fun_type<<endl;
}

void Widget::OnUtf82Str()
{
    fun_type = UTF82STR;
    do_fun_init();
    qDebug()<<"enter OnUtf82Str "<<fun_type<<endl;
}

void Widget::OnStr2Unicode()
{
    fun_type = STR2UNICODE;
    do_fun_init();
    qDebug()<<"enter OnStr2Unicode "<<fun_type<<endl;
}

void Widget::OnStr2UnicodeBig()
{
    fun_type = STR2UNICODEBIG;
    do_fun_init();
    qDebug()<<"enter OnStr2UnicodeBig "<<fun_type<<endl;
}

void Widget::OnUnicode2Str()
{
    fun_type = UNICODE2STR;
    do_fun_init();
    qDebug()<<"enter OnUnicode2Str "<<fun_type<<endl;
}

void Widget::OnUnicode2StrBig()
{
    fun_type = UNICODE2STRBIG;
    do_fun_init();
    qDebug()<<"enter OnUnicode2Str "<<fun_type<<endl;
}

void Widget::Onint2ip()
{
    fun_type = INT2IP;
    do_fun_init();
    qDebug()<<"enter Onint2ip "<<fun_type<<endl;
}

void Widget::Onip2int()
{
    fun_type = IP2INT;
    do_fun_init();
    qDebug()<<"enter Onlittle2big "<<fun_type<<endl;
}

void Widget::OnCoverBt()
{
    qDebug()<<"enter OnCoverBt fun_type "<<fun_type<<endl;
    QString hexstr;
    QString str;
    QString Md5str;
    QString Utf8str;
    QString strUtf8;
    QString strUnicode;
    QString Unicodestr;
    setInptr_str(ui->input_text_edit->toPlainText());
    switch (fun_type) {
    case STR2HEX:
        hexstr = do_str2hex(this->inptr_str);
        ui->output_text_edit->setText(hexstr.toUpper());
        break;
    case HEX2STR:
        str = do_hex2str(this->inptr_str);
        ui->output_text_edit->setText(str);
        break;
    case GENERATEMD5:
        Md5str = do_generateMd5(this->inptr_str);
        ui->output_text_edit->setText(Md5str.toUpper());
        break;
    case STR2UTF8:
        Utf8str = do_str2utf8(this->inptr_str);
        ui->output_text_edit->setText(Utf8str.toUpper());
        break;
    case UTF82STR:
        strUtf8 = do_utf82str(this->inptr_str);
        ui->output_text_edit->setText(strUtf8);
        break;
    case STR2UNICODE:
        strUnicode = do_str2unicode(this->inptr_str, false);
        ui->output_text_edit->setText(strUnicode.toUpper());
        break;
    case STR2UNICODEBIG:
        strUnicode = do_str2unicode(this->inptr_str, true);
        ui->output_text_edit->setText(strUnicode.toUpper());
        break;
    case UNICODE2STR:
        Unicodestr = do_unicode2str(this->inptr_str, false);
        ui->output_text_edit->setText(Unicodestr);
        break;
    case UNICODE2STRBIG:
        Unicodestr = do_unicode2str(this->inptr_str, true);
        ui->output_text_edit->setText(Unicodestr);
        break;
    case INT2IP:
        Unicodestr = do_int2ip(this->inptr_str);
        ui->output_text_edit->setText(Unicodestr);
        break;
    case IP2INT:
        Unicodestr = do_ip2int(this->inptr_str);
        ui->output_text_edit->setText(Unicodestr);
        break;
    default:
        break;
    }
}

void Widget::OnClearBt()
{
    clear_output_str(true);
    qDebug()<<"enter OnClearBt"<<endl;
}

void Widget::Onrandom256()
{
    do_fun_init();
    QString randomStr;
    qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
    for (int i = 0; i < 256; i++){
        randomStr += sample_str.at(qrand()%sample_str.count());
    }
    ui->output_text_edit->setText(randomStr);
}

void Widget::OnMd5()
{
    fun_type = GENERATEMD5;
    do_fun_init();
    qDebug()<<"enter OnMd5 "<<fun_type<<endl;
}

void Widget::OnMd5File()
{
    clear_output_str(true);
    QString capation = QTextCodec::codecForName("utf8")->toUnicode("打开");
    QString file_name = QFileDialog::getOpenFileName(this,capation, QDir::currentPath(),"*");
    QFile file(file_name);
    file.open(QFile::ReadOnly);
    QString filemd5 = QString(QCryptographicHash::hash(file.readAll(), QCryptographicHash::Md5).toHex());
    ui->input_text_edit->setText("input file: "+file_name);
    ui->output_text_edit->setText(filemd5.toUpper());
}

QString Widget::do_str2hex(QString str)
{
    return QString(str.toLocal8Bit().toHex());
}

QString Widget::do_hex2str(QString str)
{
#ifdef WIN32
    return QTextCodec::codecForName("gb2312")->toUnicode(QByteArray::fromHex(str.toLocal8Bit()));
#else
    return QTextCodec::codecForName("utf8")->toUnicode(QByteArray::fromHex(str.toLocal8Bit()));
#endif
}

QString Widget::do_generateMd5(QString str)
{
    return QString(QCryptographicHash::hash(str.toUtf8(), QCryptographicHash::Md5).toHex());
}

QString Widget::do_str2utf8(QString str)
{
    return QString(str.toUtf8().toHex());
}

QString Widget::do_utf82str(QString str)
{
    return QTextCodec::codecForName("utf8")->toUnicode(QByteArray::fromHex(str.toLocal8Bit()));
}

QString Widget::do_unicode2str(QString inQString, bool is_big_endian)
{
    QString desstr;
    ushort num;
    for (int i = 0; i < inQString.length();){
        QString str = inQString.mid(i, 4);
        if (is_big_endian){
            num = qToBigEndian(str.toUShort(0, 16));
        }else{
            num = str.toUShort(0, 16);
        }
//        qDebug()<<"num: "<<num<<str<<endl;
        i += 4;
        desstr.append(num);
    }
    return desstr;
}

QString Widget::do_str2unicode(QString resStr, bool is_big_endian)
{
    QString desStr, str;
    ushort ret;
    for (int i = 0; i<resStr.count();i++){
        if (is_big_endian){
            ret = qToBigEndian(resStr.at(i).unicode());
        }else {
            ret = resStr.at(i).unicode();
        }
        desStr += str.setNum(ret,16);
    }
    return desStr;
}

QString Widget::do_int2ip(QString str)
{
    bool is_hex = false;
    foreach (QChar s, str) {
        if (s < '0' || s > '9'){
            is_hex = true;
        }
    }
    uint32_t num;
    QString temp;
    if (!is_hex){
        num = str.toUInt();
    }else{
        QString hexstr = QString("%1").arg(str,8,QLatin1Char('0'));
        bool ok;
        num = hexstr.toUInt(&ok, 16);
        qDebug()<<"hex str "<<hexstr<<num<<endl;
    }
//    num = qToBigEndian(num);
    QString hexstr = temp.setNum(num, 16);
    QString decstr = temp.setNum(num, 10);
    unsigned char* p = (unsigned char *)&num;
    QString ipstr = QString("%1.%2.%3.%4").arg((num>>24)&0xff).arg((num>>16)&0xff).arg((num>>8)&0xff).arg((num)&0xff);
    return QString("Ip: %1").arg(ipstr);
}

QString Widget::do_ip2int(QString str){
    QRegExp rx(IS_IP_EXSTR);
    bool ret = rx.exactMatch(str);
    int ip_num = 0;
    if (!ret){
        return QString("ip fomat error......");
    }
    QStringList iplist = str.split(".");
    ip_num = iplist[3].toInt()|iplist[2].toInt()<<8|iplist[1].toInt()<<16|iplist[0].toInt()<<24;
    return QString("%1").arg(ip_num);
}
QString Widget::getOut_str() const
{
    return out_str;
}

void Widget::setOut_str(const QString &value)
{
    out_str = value;
}

void Widget::clear_output_str(bool clean_input)
{
    ui->output_text_edit->clear();
    this->out_str.clear();
    this->inptr_str.clear();
    if (clean_input){
        ui->input_text_edit->clear();
    }
}

void Widget::do_fun_init()
{
    ui->cover_button->setEnabled(true);
    clear_output_str();
}

QString Widget::getInptr_str() const
{
    return inptr_str;
}

void Widget::setInptr_str(const QString &value)
{
    inptr_str = value;
}
